{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "616a781c",
   "metadata": {},
   "source": [
    "<a href=\"https://colab.research.google.com/github/jerryjliu/llama_index/blob/main/docs/examples/chat_engine/chat_engine_context.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "18e20fbc-056b-44ac-b1fc-2d34b8e99bcc",
   "metadata": {},
   "source": [
    "\n",
    "# Chat Engine - Condense Plus Context Mode"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "b99eea02-429c-40e4-99be-b82a89c8d070",
   "metadata": {},
   "source": [
    "This is a multi-step chat mode built on top of a retriever over your data."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "34d34fcc-e247-4d55-ab16-c3d633e2385a",
   "metadata": {},
   "source": [
    "For each chat interaction:\n",
    "* First condense a conversation and latest user message to a standalone question\n",
    "* Then build a context for the standalone question from a retriever,\n",
    "* Then pass the context along with prompt and user message to LLM to generate a response."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f1c3cbc6-98a8-4e0e-98eb-3c7fa09ba79f",
   "metadata": {},
   "source": [
    "This approach is simple, and works for questions directly related to the knowledge base and general interactions."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca364545",
   "metadata": {},
   "source": [
    "If you're opening this Notebook on colab, you will probably need to install LlamaIndex 🦙."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a46eb19f",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install llama-index"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "79db0610",
   "metadata": {},
   "source": [
    "## Download Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ff623699",
   "metadata": {},
   "outputs": [],
   "source": [
    "!mkdir -p 'data/paul_graham/'\n",
    "!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "b314f279-bf7f-4e67-9f66-ebf783f08d38",
   "metadata": {},
   "source": [
    "## Get started in 5 lines of code"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "40d3d9e4",
   "metadata": {},
   "source": [
    "Load data and build index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a3237c7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import openai\n",
    "import os\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"sk-...\"\n",
    "openai.api_key = os.environ[\"OPENAI_API_KEY\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a9ac125a-79df-452d-9f58-ac4f30997acf",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\n",
    "from llama_index.llms import OpenAI\n",
    "\n",
    "\n",
    "service_context = ServiceContext.from_defaults(\n",
    "    llm=OpenAI(model=\"gpt-3.5-turbo\")\n",
    ")\n",
    "data = SimpleDirectoryReader(input_dir=\"./data/paul_graham/\").load_data()\n",
    "index = VectorStoreIndex.from_documents(data, service_context=service_context)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "e58d7ad9-d246-477e-acac-894ad5402f24",
   "metadata": {},
   "source": [
    "Configure chat engine\n",
    "\n",
    "Since the context retrieved can take up a large amount of the available LLM context, let's ensure we configure a smaller limit to the chat history!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "164ef191-f86a-4ce1-aa9d-64d61f29dd45",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.memory import ChatMemoryBuffer\n",
    "\n",
    "memory = ChatMemoryBuffer.from_defaults(token_limit=3900)\n",
    "\n",
    "chat_engine = index.as_chat_engine(\n",
    "    chat_mode=\"condense_plus_context\",\n",
    "    memory=memory,\n",
    "    context_prompt=(\n",
    "        \"You are a chatbot, able to have normal interactions, as well as talk\"\n",
    "        \" about an essay discussing Paul Grahams life.\"\n",
    "        \"Here are the relevant documents for the context:\\n\"\n",
    "        \"{context_str}\"\n",
    "        \"\\nInstruction: Use the previous chat history, or the context above, to interact and help the user.\"\n",
    "    ),\n",
    "    verbose=False,\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "63a4259d-89b5-49f8-b158-9eba5353d6f5",
   "metadata": {},
   "source": [
    "Chat with your data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "825b5bb3-37ff-4886-be2c-264584ca9eab",
   "metadata": {},
   "outputs": [],
   "source": [
    "response = chat_engine.chat(\"What did Paul Graham do growing up\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d8fa4310-4dc5-4787-a073-755d2e0b4887",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Growing up, Paul Graham had two main interests: writing and programming. He started by writing short stories, although he admits that they were not very good. In terms of programming, he began working with computers in 9th grade when he had access to an IBM 1401 at his school. He used an early version of Fortran and learned to write programs on punch cards. However, he found it challenging to figure out what to do with the computer since he didn't have any data stored on punched cards. Later on, with the advent of microcomputers, he got his own computer, a TRS-80, and started programming more extensively, writing simple games, prediction programs, and even a word processor.\n"
     ]
    }
   ],
   "source": [
    "print(response)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "67021e64-8665-4338-9fb4-c0f1d6361092",
   "metadata": {},
   "source": [
    "Ask a follow up question"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f6181319-5d76-48c4-a5d4-23c6e9bc5ccb",
   "metadata": {},
   "outputs": [],
   "source": [
    "response_2 = chat_engine.chat(\"Can you tell me more?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95045f5b-7964-4872-bc91-809d9debf1f5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Certainly! In addition to his early experiences with programming and writing, Paul Graham also had a fascination with computers. During his high school years, computers were quite expensive, but he managed to convince his father to buy a TRS-80, which allowed him to delve deeper into programming.\n",
      "\n",
      "While he enjoyed programming, Paul initially planned to study philosophy in college because he believed it dealt with ultimate truths. However, he found philosophy courses to be boring and lacking in substance. This led him to switch his focus to AI (Artificial Intelligence), which was gaining popularity in the mid-1980s. He was particularly inspired by a novel called \"The Moon is a Harsh Mistress\" by Heinlein, which featured an intelligent computer, and a PBS documentary showcasing Terry Winograd using SHRDLU, an early natural language processing program.\n",
      "\n",
      "During his college years, Paul Graham discovered Lisp, a programming language known for its association with AI. He found Lisp interesting not just for its connection to AI but also for its own merits. He decided to focus on Lisp and even wrote a book called \"On Lisp\" while in grad school, which was published in 1993.\n",
      "\n",
      "While studying computer science, Paul Graham realized that there was a divide between theory and systems in the field. He was more inclined towards building things rather than proving theoretical concepts. However, he also recognized that software developed in the systems domain would eventually become obsolete. This dissatisfaction led him to explore other avenues, and he discovered a passion for art, specifically painting. He realized that paintings could last for centuries and decided to take art classes at Harvard while still pursuing his PhD in computer science.\n",
      "\n",
      "Ultimately, Paul Graham found himself juggling multiple projects, including his thesis, Lisp hacking, and his newfound interest in art. However, an opportunity presented itself when his advisor asked if he was close to graduating. Despite not having written a word of his dissertation, he decided to take a chance and wrote it within a short timeframe, incorporating parts of his book \"On Lisp.\" This allowed him to complete his PhD and move forward with his career.\n"
     ]
    }
   ],
   "source": [
    "print(response_2)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c2c68de8-af58-4f7e-8759-19fc072873fd",
   "metadata": {},
   "source": [
    "Reset conversation state"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d13cf082-1a91-43c5-8bad-76fa45be96f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "chat_engine.reset()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "627de435-d195-4dad-b314-a68e731979a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "response = chat_engine.chat(\"Hello! What do you know?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75ef9e31-3cdb-4129-92f7-e61be201ea36",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello! As an AI chatbot, I have access to a wide range of information. I can provide general knowledge, answer questions, engage in conversations, and assist with various topics. Is there something specific you would like to know or discuss?\n"
     ]
    }
   ],
   "source": [
    "print(response)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "a65ad1a2",
   "metadata": {},
   "source": [
    "## Streaming Support"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad272dfe",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index import (\n",
    "    ServiceContext,\n",
    "    VectorStoreIndex,\n",
    "    SimpleDirectoryReader,\n",
    "    set_global_service_context,\n",
    ")\n",
    "from llama_index.llms import OpenAI\n",
    "\n",
    "service_context = ServiceContext.from_defaults(\n",
    "    llm=OpenAI(model=\"gpt-3.5-turbo\", temperature=0)\n",
    ")\n",
    "set_global_service_context(service_context)\n",
    "\n",
    "data = SimpleDirectoryReader(input_dir=\"./data/paul_graham/\").load_data()\n",
    "\n",
    "index = VectorStoreIndex.from_documents(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "22605caa",
   "metadata": {},
   "outputs": [],
   "source": [
    "chat_engine = index.as_chat_engine(\n",
    "    chat_mode=\"condense_plus_context\",\n",
    "    context_prompt=(\n",
    "        \"You are a chatbot, able to have normal interactions, as well as talk\"\n",
    "        \" about an essay discussing Paul Grahams life.\"\n",
    "        \"Here are the relevant documents for the context:\\n\"\n",
    "        \"{context_str}\"\n",
    "        \"\\nInstruction: Based on the above documents, provide a detailed answer for the user question below.\"\n",
    "    ),\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "250abd43",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "After Y Combinator (YC), Paul Graham made a significant decision to step back from his role in YC and pursue other endeavors. In 2012, his mother had a stroke caused by colon cancer, which led him to reevaluate his priorities. He realized that YC was consuming more of his attention and that he was ready to hand over the reins to someone else.\n",
      "\n",
      "Paul approached Jessica Livingston, his wife and co-founder of YC, to take over as president, but she declined. Eventually, they recruited Sam Altman, who initially wanted to start a startup focused on nuclear reactors. However, Paul persisted in convincing Sam to join YC, and in October 2013, Sam agreed to become the president of YC.\n",
      "\n",
      "During the transition period, Paul gradually handed over the responsibilities of running YC to Sam, allowing him to learn the job. This allowed Paul to focus on his mother, who was battling cancer. Ultimately, Paul retired from his active role in YC, along with co-founder Robert Morris, while Jessica Livingston and Trevor Blackwell continued as ordinary partners.\n",
      "\n",
      "After leaving YC, Paul Graham embarked on new ventures. One notable project was starting his own investment firm. Alongside Jessica, Robert, and Trevor, he founded an investment firm to implement the ideas they had been discussing. This move allowed them to fund startups and provide the support they wished they had received when they were starting out.\n",
      "\n",
      "Additionally, Paul continued to write essays, which had been one of his ongoing projects even during his time at YC. These essays covered a wide range of topics, including startups, technology, and life lessons. Paul's essays gained significant popularity and became a valuable resource for aspiring entrepreneurs and tech enthusiasts.\n",
      "\n",
      "Overall, after YC, Paul Graham focused on his investment firm, writing essays, and exploring new opportunities outside of YC."
     ]
    }
   ],
   "source": [
    "response = chat_engine.stream_chat(\"What did Paul Graham do after YC?\")\n",
    "for token in response.response_gen:\n",
    "    print(token, end=\"\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
